# start.s begin
.global _start
.global exception_handler

.text

# _start 是CPU复位后的入口点
_start:
    # 1. 设置异常处理程序的地址到 mtvec 寄存器
    la t0, exception_handler
    # la t0, halt
    csrw mtvec, t0

    # 读取硬件线程ID，确保我们在0号核心上运行
    csrr t0, mhartid
    bnez t0, halt        # 如果不是0号核心，进入halt

    # 2. 设置堆栈指针（从链接脚本中获取栈顶地址）
    la sp, _stack_top

    # 将所有地址设置为可读写执行
    li t0, 0xFFFFFFFF       # NAPOT编码：最低32位全为1
    csrw pmpaddr0, t0       # 区域大小 = 2^(32) = 4GB

    li t1, 0x1F             # 访问权限(A=3, R=1, W=1, X=1, L=0)
    csrw pmpcfg0, t1

    csrw pmpcfg1, 0         # 禁用 PMP 的 8-15

    # 3. 设置mstatus寄存器：清除MPP位(11-12位)
    li t0, 0x1800        # MPP位掩码(第11-12位)
    csrrc t1, mstatus, t0  # 清除指定比特位

    # 4. 设置异常返回地址并触发返回
    la t0, kernel_main
    csrw mepc, t0        # 设置异常返回地址
    mret                 # 跳转到kernel_main

# exception_handler 是所有异常（包括中断）的统一入口
exception_handler:
    # 保存所有31个通用寄存器到栈上
    addi sp, sp, -128
    sw x1, 0 * 4(sp)
    sw x2, 1 * 4(sp)
    sw x3, 2 * 4(sp)
    sw x4, 3 * 4(sp)
    sw x5, 4 * 4(sp)
    sw x6, 5 * 4(sp)
    sw x7, 6 * 4(sp)
    sw x8, 7 * 4(sp)
    sw x9, 8 * 4(sp)
    sw x10, 9 * 4(sp)
    sw x11, 10 * 4(sp)
    sw x12, 11 * 4(sp)
    sw x13, 12 * 4(sp)
    sw x14, 13 * 4(sp)
    sw x15, 14 * 4(sp)
    sw x16, 15 * 4(sp)
    sw x17, 16 * 4(sp)
    sw x18, 17 * 4(sp)
    sw x19, 18 * 4(sp)
    sw x20, 19 * 4(sp)
    sw x21, 20 * 4(sp)
    sw x22, 21 * 4(sp)
    sw x23, 22 * 4(sp)
    sw x24, 23 * 4(sp)
    sw x25, 24 * 4(sp)
    sw x26, 25 * 4(sp)
    sw x27, 26 * 4(sp)
    sw x28, 27 * 4(sp)
    sw x29, 28 * 4(sp)
    sw x30, 29 * 4(sp)
    sw x31, 30 * 4(sp)
    
    # 调用C语言编写的异常处理函数
    call c_exception_handler

    # 恢复寄存器
    lw x1, 0 * 4(sp)
    lw x2, 1 * 4(sp)
    lw x3, 2 * 4(sp)
    lw x4, 3 * 4(sp)
    lw x5, 4 * 4(sp)
    lw x6, 5 * 4(sp)
    lw x7, 6 * 4(sp)
    lw x8, 7 * 4(sp)
    lw x9, 8 * 4(sp)
    lw x10, 9 * 4(sp)
    lw x11, 10 * 4(sp)
    lw x12, 11 * 4(sp)
    lw x13, 12 * 4(sp)
    lw x14, 13 * 4(sp)
    lw x15, 14 * 4(sp)
    lw x16, 15 * 4(sp)
    lw x17, 16 * 4(sp)
    lw x18, 17 * 4(sp)
    lw x19, 18 * 4(sp)
    lw x20, 19 * 4(sp)
    lw x21, 20 * 4(sp)
    lw x22, 21 * 4(sp)
    lw x23, 22 * 4(sp)
    lw x24, 23 * 4(sp)
    lw x25, 24 * 4(sp)
    lw x26, 25 * 4(sp)
    lw x27, 26 * 4(sp)
    lw x28, 27 * 4(sp)
    lw x29, 28 * 4(sp)
    lw x30, 29 * 4(sp)
    lw x31, 30 * 4(sp)
    addi sp, sp, 128
    
    # 从异常返回
    mret

halt:
    # 其他核心或处理完异常后进入等待状态
    wfi                 # 等待中断
    j halt

# start.s end